package com.example.pt.service.impl;

import com.example.pt.entity.TorrentFile;
import com.example.pt.entity.User;
import com.example.pt.mapper.UserTransferStatsMapper;
import com.example.pt.repository.TorrentFileRepository;
import com.example.pt.repository.UserRepositories;
import com.example.pt.service.TorrentMonitorService;
import com.example.pt.service.UserService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.time.Duration;
import java.time.Instant;
import java.time.LocalDateTime;
import java.util.*;

@Service
@Transactional
public class TorrentMonitorServiceImpl implements TorrentMonitorService {

    @Autowired
    private TorrentFileRepository torrentFileRepository;

    @Autowired
    private UserTransferStatsMapper userTransferStatsRepository;
    @Autowired
    private UserService userService;
    @Autowired
    private UserRepositories userRepositories;



    @Override
    public void executeDailyMonitoring() {
        System.out.println("开始检测");
        Calendar calendar = Calendar.getInstance();
        calendar.add(Calendar.DAY_OF_MONTH, -1);
//        Date thresholdTime = calendar.getTime();//现在？
//        String yesterday = new java.sql.Date(calendar.getTimeInMillis()).toString();

        // 检测异常种子
        List<Integer> abnormalTorrentIds = detectAbnormalTorrents();

        // 检测作弊用户
        List<Integer> cheatUserIds = detectCheatUsers(abnormalTorrentIds);

        // 封禁作弊用户
        banCheatUsers(cheatUserIds);
    }

    @Override
    public List<Integer> detectAbnormalTorrents() {//得到异常种子id
        System.out.println("监测异常种子");
        List<Integer> abnormalTorrentIds = new ArrayList<>();
//        String yesterday = new java.sql.Date(System.currentTimeMillis() - 86400000).toString();

        List<Map<String, Object>> statsList = userTransferStatsRepository.calculateStatsByTorrent();

        for (Map<String, Object> stats : statsList) {//遍历种子
            Number totalUploaded = (Number) stats.get("totalUploaded");
            Number totalDownloaded = (Number) stats.get("totalDownloaded");

            Long dailyUploaded = totalUploaded != null ? totalUploaded.longValue() : 0L;
            Long dailyDownloaded = totalDownloaded != null ? totalDownloaded.longValue() : 0L;
            int tid  = (int)stats.get("tid");
            Optional<TorrentFile> torrentfile = torrentFileRepository.findByTid(tid);
            TorrentFile tf = torrentfile.get();
            LocalDateTime now = LocalDateTime.now(); // 获取当前时间
            Duration duration = Duration.between(tf.getUploadTime(), now); // 计算时间差
            System.out.println("tid: "+tid+", uploaded: "+dailyUploaded);
            System.out.println("tid: "+tid+", downloaded: "+dailyDownloaded);
            // 跳过上传时间小于24小时的种子（新种子不检测）
            if (duration.toHours() < 24) {
                System.out.println("没搜素");
                continue;
            }
            if (dailyUploaded > 0 && dailyDownloaded > 0 &&
                    (double) dailyUploaded / dailyDownloaded > 2.0) {
                abnormalTorrentIds.add((Integer) stats.get("tid"));
                System.out.println("tid为"+tid+"的种子文件上传下载量异常。");
            }
        }


        return abnormalTorrentIds;
    }

    @Override
    public List<Integer> detectCheatUsers(List<Integer> abnormalTorrentIds) {
        System.out.println("检查作弊用户");
        if (abnormalTorrentIds.isEmpty()) {
            System.out.println("作弊种子文件为空");
            return Collections.emptyList();
        }

        List<Integer> cheatUserIds = new ArrayList<>();
//        List<Map<String, Object>> userStatsList = userTransferStatsRepository.findUserStatsByAbnormalTorrents(abnormalTorrentIds);

        for (int tid:abnormalTorrentIds) {
            // 提取字段并处理null值
            List<Map<String, Object>> userStatss = userTransferStatsRepository.findUserStatsByAbnormalTorrents(tid);

            for(Map<String, Object>userStats:userStatss){
                Long fileSize = getLongValue(userStats, "fileSize");
                Long downloaded = getLongValue(userStats, "downloaded");
                Long uploaded = getLongValue(userStats, "uploaded");
                Integer uid = getIntegerValue(userStats, "userId");
                System.out.println("正在检测UID: "+uid+"\n");
                Integer level = getIntegerValue(userStats, "level");
                Integer seedHours = getIntegerValue(userStats, "seedDays");  // 直接使用SQL返回的值

                // 跳过高等级用户
                if (level != null && level >= 4) {
                    System.out.println("用户等级高于4，不检测");
                    continue;
                }

                // 条件1：下载量不足文件大小10%但有上传
                boolean condition1 = (downloaded != null && fileSize != null && uploaded != null)
                        && (downloaded < fileSize * 0.1 && uploaded > 0);

                // 条件2：做种时间不足24小时但上传量超过文件大小5倍
                boolean condition2 = (seedHours != null && fileSize != null && uploaded != null)
                        && (seedHours < 1 && uploaded > fileSize * 5);

                if (condition1 || condition2) {
                    System.out.println("判断为作弊用户");
                    cheatUserIds.add(uid);
                }
            }
        }
        return cheatUserIds;
    }

    private Long getLongValue(Map<String, Object> map, String key) {
        Object value = map.get(key);
        if (value instanceof Number) {
            return ((Number) value).longValue();
        }
        return null;
    }

    private Integer getIntegerValue(Map<String, Object> map, String key) {
        Object value = map.get(key);
        if (value instanceof Number) {
            return ((Number) value).intValue();
        }
        return null;
    }
    @Override
    public void banCheatUsers(List<Integer> cheatUserIds) {
        // 实现用户封禁逻辑
        for(int userID:cheatUserIds){
            userService.banUsers(userID);
            System.out.println("封禁作弊用户: " + userID);
        }
        System.out.println("封禁作弊用户完成");
        // 实际项目中需要调用用户服务实现封禁
    }
}